package io.github.junxworks.qt.modules.mm.engine.handlers;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import io.github.junxworks.ep.qlexp.ExecResult;
import io.github.junxworks.ep.qlexp.RuleEngine;
import io.github.junxworks.ep.qlexp.SpringQLContext;
import io.github.junxworks.junx.core.exception.BaseRuntimeException;
import io.github.junxworks.junx.core.util.ExceptionUtils;
import io.github.junxworks.junx.event.EventChannel;
import io.github.junxworks.junx.event.EventChannelHandler;
import io.github.junxworks.junx.event.EventContext;
import io.github.junxworks.qt.config.Params;
import io.github.junxworks.qt.config.Topics;
import io.github.junxworks.qt.modules.mm.engine.CtxHolder;
import io.github.junxworks.qt.modules.mm.engine.DataContext;
import io.github.junxworks.qt.modules.mm.engine.ExeContext;
import io.github.junxworks.qt.modules.mm.engine.functions.Functions;
import io.github.junxworks.qt.modules.mm.entity.RExpResult;
import io.github.junxworks.qt.modules.mm.vo.MmExpressionVo;

@Component
public class ExpressionHandler implements EventChannelHandler {

	@Autowired
	private RuleEngine engine;

	@Override
	public void handleEvent(EventContext event, EventChannel channel) throws Exception {
		DataContext data = event.getData(DataContext.class, Params.DATA_CONTEXT);
		ExeContext exeContext = data.getExeContext();
		CtxHolder.setContext(data);
		try {
			if (!data.isDone()) {
				if (!exeContext.shouldExecuteExp()) {
					data.done();
					return;
				}
				String key = data.getKey().getValue();
				String column = data.getKey().getColumn();
				String tradeDate = exeContext.getTradeDate();
				List<MmExpressionVo> exps = exeContext.getExpressions();
				exps.forEach(e -> {
					SpringQLContext qlCtx = new SpringQLContext();
					qlCtx.put("exeContext", exeContext);
					ExecResult execRes = null;
					try {
						execRes = engine.execute(e.getExpression(), qlCtx);
						if (!execRes.isSuccess()) {
							throw new BaseRuntimeException("表达式[" + e.getExpName() + "]执行异常:" + execRes.getErrorMsg());
						}
						String ekey = Functions.createKeyName(e.getExpName(), key);
						exeContext.putExpressionResults(ekey, execRes.getResult());
						RExpResult mr = new RExpResult();
						mr.setKeyName(column);
						mr.setKeyValue(key);
						mr.setName(e.getExpName());
						mr.setValue(Double.valueOf(String.valueOf(execRes.getResult())));
						mr.setTradeDate(tradeDate);
						EventContext ctx = new EventContext(Topics.STORE_EXP_RES);
						ctx.setData(Params.PARAM_STORE_OBJ, mr);
						channel.publish(Topics.STORE_EXP_RES, ctx);
					} catch (Throwable t) {
						throw new BaseRuntimeException("表达式["+e.getExpName()+"]执行失败，失败原因：%s", ExceptionUtils.getCauseMessage(t));
					}
				});
				EventContext ctx = new EventContext(Topics.MODEL);
				ctx.setData(Params.DATA_CONTEXT, data);
				channel.publish(Topics.MODEL, ctx);
			}
		} catch (Throwable e) {
			data.setException(e);
		} finally {
			CtxHolder.remove();
		}
	}

}
